#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <stdint.h>

#define NTHREADS 8
#define START 22

long fib(long n);

void *eight_thread_function(void *thread_num)
{
    int id = (intptr_t)thread_num;
    long tid;
    tid = (long)thread_num;
    printf("Fib(%ld)=%ld\n", tid, fib(tid));
}

void *four_thread_function(void * thread_num)
{
    int id = (intptr_t)thread_num;
    long tid;
    tid = (long)thread_num;
    printf("Fib(%ld)=%ld\n", tid, fib(tid));
    printf("Fib(%ld)=%ld\n", tid + 2, fib(tid + 2));
}

long fib(long n)
{
    long new, first_num = 0, second_num = 1, fib_num, i;
    for (i = 0; i <= n; i++) {
        if (i <= 1) {
            fib_num = i;
        } else {
            fib_num = first_num + second_num;
            first_num = second_num;
            second_num = fib_num; 
        }
    }
    return fib_num;
    //......
}

long toddiff(struct timeval *tod1, struct timeval *tod2)
{
    long t1, t2;
    t1 = tod1->tv_sec * 1000000 + tod1->tv_usec;
    t2 = tod2->tv_sec * 1000000 + tod2->tv_usec;
    return t1 - t2;
}

int main(int argc, char *argv[])
{
    
    pthread_t thread_id[NTHREADS];
    int i, j, k, rc;
    int threaded = atoi(argv[1]);
    printf("Argument was: %d\n", threaded);
    struct timeval begin, end;
    gettimeofday(&begin, NULL);
    
    if (threaded == 0) {
        for(i = 0; i < NTHREADS; i++)
        {
            j = i*2 + START;
            
            if (!threaded) {
                printf("Fib(%d)=%ld\n",j ,fib(j));
            }
        }
    }
    if (threaded == 8) {
        for(i = 0; i < NTHREADS; i++)
        {
            j = i*2 + START;

            rc = pthread_create(&thread_id[i], NULL, eight_thread_function, (void *)(intptr_t)j);
            if (rc){
                printf("ERROR; return code from pthread_create() is %d\n", rc);
                exit(-1);
            }
        }

        for(k = 0; k < NTHREADS; k++)
        {
            pthread_join(thread_id[k], NULL);
        }
    }

    if (threaded == 4) {
        for(i = 0; i < NTHREADS / 2; i++) {
            j = i * 4 + START;

            rc = pthread_create(&thread_id[i], NULL, four_thread_function, (void *)(intptr_t)j);
            if (rc){
                printf("ERROR; return code from pthread_create() is %d\n", rc);
                exit(-1);
            }
        }

        for(k = 0; k < NTHREADS / 2; k++)
        {
            pthread_join(thread_id[k], NULL);
        }
    }
    //clock_t end=clock();
    gettimeofday(&end, NULL);
    
    printf("Unthreaded time elapsed: %f ms\n", (toddiff(&end,&begin))/1000.0);
	return 0;

    pthread_exit(NULL);
}

